import mss
import cv2
import numpy as np
from typing import Dict, Tuple, List, NamedTuple
from pynput.keyboard import Controller, Key
import time
import threading# 用于点击

from utils import press_key, click_mouse
# ==================== 数据结构 ====================
class MapState(NamedTuple):
    rooms: List[bool]      # 8 个房间是否已通关
    in_dungeon: bool       # 是否已进入副本
    state_code: str        # 8 位二进制字符串

# ==================== 主类 ====================
class DNFSkillAutoCaster:
    def __init__(self, release_interval: float = 1.3):
        # === 技能系统保持不变 ===
        self.skill_region = {"left": 438, "top": 536, "width": 211, "height": 58}
        self.reinforce_region = {"left": 1000, "top": 486, "width": 10, "height": 10}
        self.cols, self.rows = 7, 2
        self.SATURATION_THRESHOLD = 5
        self.SAMPLE_RADIUS = self._get_max_safe_radius()
        self.reinforce_radius = min(self.reinforce_region["width"]//3, 2)

        self.skill_keys = [
            ['q', 'w', 'e', 'r', 't', 'y', '8'],
            ['a', 's', 'd', 'f', 'g', 'h', '9']
        ]
        self.release_order = [
            'q', 'w', 'e', 'r', 't', 'y', '8',
            'a', 's', 'd', 'f', 'g', 'h', '9',
            'tab', 'x'
        ]
        self.release_interval = release_interval
        self.keyboard = Controller()
        self.running = False
        self.last_release_time = 0

        # === 新增：地图系统 ===
        self.map_region = {
            "left": 937,      # 请根据实际截图调整
            "top": 50,
            "width": 125,
            "height": 14
        }
        self.room_grid = [
            (0,0), (1,0), (2,0), (3,0),
            (4,0), (5,0), (6,0)
        ]
        self.room_padding = 1
        self.entry_region_rel = {"left": 120, "top": 160, "width": 60, "height": 30}
        self.BRIGHTNESS_CLEARED = 180

        print(f"[初始化] 技能栏: {self.skill_region['width']}x{self.skill_region['height']}, "
              f"地图: {self.map_region['width']}x{self.map_region['height']}")
        self.prev_map_frame = None  # 上一帧地图
        self.flash_cooldown = {}    # 防止重复触发

        # self.create_hsv_tuner()

    def create_hsv_tuner(self):
        """打开 HSV 调参窗口，实时看到蓝色区域"""
        cv2.namedWindow("HSV Tuner", cv2.WINDOW_NORMAL)
        cv2.createTrackbar("H Min", "HSV Tuner", 100, 179, lambda x: None)
        cv2.createTrackbar("H Max", "HSV Tuner", 115, 179, lambda x: None)
        cv2.createTrackbar("S Min", "HSV Tuner", 112, 255, lambda x: None)
        cv2.createTrackbar("S Max", "HSV Tuner", 255, 255, lambda x: None)
        cv2.createTrackbar("V Min", "HSV Tuner", 164, 255, lambda x: None)
        cv2.createTrackbar("V Max", "HSV Tuner", 255, 255, lambda x: None)
        print("[调参] 打开 HSV Tuner 窗口，拖动滑块直到只看到小人")

    def find_blue_player_tune(self, img_bgr: np.ndarray) -> Tuple[int, int] | None:
        hsv = cv2.cvtColor(img_bgr, cv2.COLOR_BGR2HSV)

        # 实时读取滑块
        h_min = cv2.getTrackbarPos("H Min", "HSV Tuner")
        h_max = cv2.getTrackbarPos("H Max", "HSV Tuner")
        s_min = cv2.getTrackbarPos("S Min", "HSV Tuner")
        s_max = cv2.getTrackbarPos("S Max", "HSV Tuner")
        v_min = cv2.getTrackbarPos("V Min", "HSV Tuner")
        v_max = cv2.getTrackbarPos("V Max", "HSV Tuner")

        lower = np.array([h_min, s_min, v_min])
        upper = np.array([h_max, s_max, v_max])
        mask = cv2.inRange(hsv, lower, upper)

        # 显示
        vis = img_bgr.copy()
        vis[mask > 0] = [0, 0, 255]  # 蓝色区域变红
        cv2.imshow("HSV Tuner", vis)
        cv2.imshow("Mask", mask)

        # 找轮廓
        contours, _ = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
        if not contours:
            return None

        largest = max(contours, key=cv2.contourArea)
        if cv2.contourArea(largest) < 5:
            return None

        M = cv2.moments(largest)
        if M["m00"] == 0:
            return None
        cx = int(M["m10"] / M["m00"])
        cy = int(M["m01"] / M["m00"])

        # cv2.circle(vis, (cx, cy), 10, (0, 255, 0), -1)
        # cv2.putText(vis, "Player", (cx+15, cy), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0,255,0), 2)
        cv2.imshow("HSV Tuner", vis)


        key = cv2.waitKey(1) & 0xFF
        if key == ord('q'):
            cv2.destroyAllWindows()

        return (cx, cy)

    def create_flash_debug_window(self):
        """创建调参窗口"""
        cv2.namedWindow("Flash Debug", cv2.WINDOW_NORMAL)
        cv2.createTrackbar("Thresh", "Flash Debug", 35, 100, lambda x: None)
        cv2.createTrackbar("Min %", "Flash Debug", 15, 50, lambda x: None)
        cv2.createTrackbar("Radius", "Flash Debug", 12, 30, lambda x: None)
        cv2.createTrackbar("Morph", "Flash Debug", 5, 15, lambda x: None)
        print("[调参] 打开 Flash Debug 窗口，拖动滑块实时调整")

    def detect_flashing_rooms(self, debug: bool = True) -> List[int]:
        
        with mss.mss() as sct:
            raw = sct.grab(self.map_region)
            img = np.array(raw)[:, :, :3]

        if self.prev_map_frame is None:
            self.prev_map_frame = img.copy()
            if debug:
                print("[闪烁检测] 第一帧，初始化...")
            # self.create_flash_debug_window()
            return []

        # 1. 读取实时参数
        # thresh = cv2.getTrackbarPos("Thresh", "Flash Debug")
        # min_ratio = cv2.getTrackbarPos("Min %", "Flash Debug") / 100.0
        # radius = cv2.getTrackbarPos("Radius", "Flash Debug")
        # morph_size = cv2.getTrackbarPos("Morph", "Flash Debug")
        thresh = 40
        min_ratio = 0.25
        radius = 4
        morph_size = 3
        if morph_size % 2 == 0:
            morph_size += 1

        # 2. 帧差
        diff = cv2.absdiff(img, self.prev_map_frame)
        gray = cv2.cvtColor(diff, cv2.COLOR_BGR2GRAY)
        _, binary = cv2.threshold(gray, thresh, 255, cv2.THRESH_BINARY)

        # 3. 去噪
        kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (morph_size, morph_size))
        binary = cv2.morphologyEx(binary, cv2.MORPH_OPEN, kernel)
        binary = cv2.morphologyEx(binary, cv2.MORPH_CLOSE, kernel)

        # 4. 可视化
        vis = img.copy()
        mask_colored = cv2.cvtColor(binary, cv2.COLOR_GRAY2BGR)
        centers_rel = [(x - self.map_region["left"], y - self.map_region["top"]) 
                    for x, y in self._get_room_centers()]

        flashing = []
        now = time.time()

        for i, (cx, cy) in enumerate(centers_rel):
            x1 = max(0, int(cx - radius))
            y1 = max(0, int(cy - radius))
            x2 = min(binary.shape[1], int(cx + radius))
            y2 = min(binary.shape[0], int(cy + radius))
            region = binary[y1:y2, x1:x2]

            white_pixels = np.sum(region == 255)
            area = region.size
            ratio = white_pixels / area if area > 0 else 0

            # 画框
            color = (0, 255, 255) if ratio > min_ratio else (0, 100, 255)
            cv2.rectangle(vis, (x1, y1), (x2, y2), color, 2)
            cv2.putText(vis, f"{i+1}", (cx-10, cy-10), cv2.FONT_HERSHEY_SIMPLEX, 0.6, color, 2)
            cv2.putText(vis, f"{ratio:.2f}", (cx-10, cy+15), cv2.FONT_HERSHEY_SIMPLEX, 0.4, (255,255,0), 1)

            if ratio > min_ratio:
                # if i not in self.flash_cooldown or now - self.flash_cooldown[i] > 1.5:
                flashing.append(i)
                self.flash_cooldown[i] = now

        # 5. 显示
        h, w = img.shape[:2]
        combined = np.zeros((h, w*2, 3), dtype=np.uint8)
        combined[:, :w] = vis
        combined[:, w:] = mask_colored
        # cv2.imshow("Flash Debug", combined)

        # # 6. 按 q 退出调试
        # if cv2.waitKey(1) & 0xFF == ord('q'):
        #     cv2.destroyWindow("Flash Debug")

        self.prev_map_frame = img.copy()
        return flashing
    def find_blue_player(self, img_bgr: np.ndarray, debug: bool = False) -> Tuple[int, int] | None:
        """
        返回小人在地图上的 **相对坐标 (x, y)**，或 None
        debug=True 时会弹出窗口 + 保存图片
        """
        # 1. 转 HSV
        hsv = cv2.cvtColor(img_bgr, cv2.COLOR_BGR2HSV)

        # 2. 蓝色范围（可调！）
        lower_blue = np.array([100, 112, 164])   # H:100~120, S:120+, V:80+
        upper_blue = np.array([115, 255, 255])

        # 3. 生成掩膜
        mask = cv2.inRange(hsv, lower_blue, upper_blue)

        # 4. 查找轮廓
        contours, _ = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
        if debug:
            print(f"[调试] 找到 {len(contours)} 个蓝色区域")

        if not contours:
            if debug:
                self._show_debug("No blue contours", img_bgr, mask, None)
            return None

        # 5. 筛选：面积 > 5 像素
        valid_contours = [c for c in contours if cv2.contourArea(c) >= 5]
        if debug:
            print(f"[调试] 有效轮廓（面积≥5）: {len(valid_contours)} 个")

        if not valid_contours:
            if debug:
                self._show_debug("No valid size", img_bgr, mask, None)
            return None

        # 6. 找最大轮廓
        largest = max(valid_contours, key=cv2.contourArea)
        area = cv2.contourArea(largest)
        if debug:
            print(f"[调试] 最大轮廓面积: {area:.1f} 像素")

        # 7. 计算质心
        M = cv2.moments(largest)
        if M["m00"] == 0:
            if debug:
                self._show_debug("m00=0", img_bgr, mask, largest)
            return None

        cx = int(M["m10"] / M["m00"])
        cy = int(M["m01"] / M["m00"])
        if debug:
            print(f"[调试] 小人位置: ({cx}, {cy})")

        # 8. 可视化 + 保存
        if debug:
            vis = img_bgr.copy()
            cv2.drawContours(vis, [largest], -1, (0, 255, 0), 2)
            cv2.circle(vis, (cx, cy), 8, (255, 0, 0), -1)
            cv2.putText(vis, f"{area:.0f}", (cx + 10, cy), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (255, 255, 0), 2)

            self._show_debug(f"Found! Area={area:.0f}", vis, mask, largest)

        return (cx, cy)
    
    def _show_debug(self, title: str, img_rgb, mask, contour):
        """显示调试窗口 + 保存图片"""
        # 组合图像：原图 + 掩膜 + 轮廓
        h, w = img_rgb.shape[:2]
        combined = np.zeros((h, w * 3, 3), dtype=np.uint8)
        combined[:, :w] = img_rgb
        combined[:, w:2*w] = cv2.cvtColor(mask, cv2.COLOR_GRAY2BGR)
        if contour is not None:
            temp = img_rgb.copy()
            cv2.drawContours(temp, [contour], -1, (0, 255, 0), 1)
            combined[:, 2*w:] = temp
        else:
            combined[:, 2*w:] = img_rgb

        # cv2.putText(combined, title, (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 255), 2)

        # 显示
        cv2.imshow("Blue Player Debug", combined)
        cv2.waitKey(2000)

        # 保存
        timestamp = int(time.time() * 1000)
        cv2.imwrite(f"debug_player_{timestamp}.png", combined)
        print(f"[调试] 已保存 debug_player_{timestamp}.png")

    def get_current_room(self) -> int:
        """返回 0~7 房间编号"""
        with mss.mss() as sct:
            raw = sct.grab(self.map_region)
        img = np.array(raw)[:, :, :3]

        pos = self.find_blue_player(img)
        # pos = self.find_blue_player_tune(img)
        if not pos:
            # print("未找到小人")
            return -1  # 未找到

        rel_x, rel_y = pos
        centers = self._get_room_centers()  # 绝对坐标
        room_centers_rel = [(x - self.map_region["left"], y - self.map_region["top"]) for x, y in centers]
        
        # print("pos",pos,room_centers_rel)
        # 找最近的房间
        min_dist = float('inf')
        current_room = -1
        for i, (rx, ry) in enumerate(room_centers_rel):
            dist = (rel_x - rx)**2 + (rel_y - ry)**2
            if dist < min_dist:
                min_dist = dist
                current_room = i
        return current_room if min_dist < 2000 else -1  # 距离阈值
    # ==================== 技能检测（保持不变） ====================
    def _get_max_safe_radius(self):
        cell_w = self.skill_region["width"] // self.cols
        cell_h = self.skill_region["height"] // self.rows
        return min((cell_w - 1) // 2, (cell_h - 1) // 2, 3)

    def _get_skill_centers(self) -> Dict[str, Tuple[int, int]]:
        left, top = self.skill_region["left"], self.skill_region["top"]
        cell_w = self.skill_region["width"] // self.cols
        cell_h = self.skill_region["height"] // self.rows
        centers = {}
        keys = ['q','w','e','r','t','y','8','a','s','d','f','g','h','9']
        for i, key in enumerate(keys):
            row, col = divmod(i, self.cols)
            x = left + col * cell_w + cell_w // 2
            y = top + row * cell_h + cell_h // 2
            centers[key] = (x, y)
        return centers

    def _get_reinforce_center(self) -> Tuple[int, int]:
        r = self.reinforce_region
        return (r["left"] + r["width"]//2, r["top"] + r["height"]//2)

    def _sample_center_color(self, img_bgr: np.ndarray, center_abs: Tuple[int, int], region: Dict) -> float:
        ox, oy = region["left"], region["top"]
        x_rel, y_rel = center_abs[0] - ox, center_abs[1] - oy
        r = self.SAMPLE_RADIUS if region is self.skill_region else self.reinforce_radius
        h, w = img_bgr.shape[:2]
        y1, y2 = max(0, y_rel - r), min(h, y_rel + r + 1)
        x1, x2 = max(0, x_rel - r), min(w, x_rel + r + 1)
        if y2 <= y1 or x2 <= x1:
            return 0.0
        patch = img_bgr[y1:y2, x1:x2]
        hsv = cv2.cvtColor(patch, cv2.COLOR_BGR2HSV)
        return np.mean(hsv[:, :, 1])

    def detect_all_skills(self) -> Dict[str, str]:
        with mss.mss() as sct:
            raw_skill = sct.grab(self.skill_region)
        img_skill = np.array(raw_skill)[:, :, :3]
        skill_centers = self._get_skill_centers()
        skills = {}
        for key, center in skill_centers.items():
            s = self._sample_center_color(img_skill, center, self.skill_region)
            skills[key] = "available" if s >= self.SATURATION_THRESHOLD else "cooldown"

        with mss.mss() as sct:
            raw_reinforce = sct.grab(self.reinforce_region)
        img_reinforce = np.array(raw_reinforce)[:, :, :3]
        tab_center = self._get_reinforce_center()
        s = self._sample_center_color(img_reinforce, tab_center, self.reinforce_region)
        skills["tab"] = "available" if s >= self.SATURATION_THRESHOLD else "cooldown"
        skills["x"] = "available"
        return skills

    # ==================== 地图检测（新增） ====================
    def _get_room_centers(self) -> List[Tuple[int, int]]:
        left, top = self.map_region["left"], self.map_region["top"]
        total_w, total_h = self.map_region["width"], self.map_region["height"]

        # todo auto get from self.room_grid
        cell_w = (total_w - self.room_padding * 5) // 7
        cell_h = (total_h - self.room_padding * 3) // 1
        centers = []
        for col, row in self.room_grid:
            px = self.room_padding * (col + 1)
            py = self.room_padding * (row + 1)
            x = left + px + col * cell_w + cell_w // 2
            y = top + py + row * cell_h + cell_h // 2
            centers.append((x, y))
        return centers

    def _sample_point(self, img_bgr: np.ndarray, center_rel: Tuple[int, int]) -> Tuple[float, float, float]:
        x, y = center_rel
        r = 4
        h, w = img_bgr.shape[:2]
        y1, y2 = max(0, y - r), min(h, y + r + 1)
        x1, x2 = max(0, x - r), min(w, x + r + 1)
        if y2 <= y1 or x2 <= x1:
            return 0, 0, 0
        patch = img_bgr[y1:y2, x1:x2]
        hsv = cv2.cvtColor(patch, cv2.COLOR_BGR2HSV)
        return tuple(np.mean(hsv, axis=(0,1)))

    def detect_map_state(self) -> MapState:
        with mss.mss() as sct:
            raw = sct.grab(self.map_region)
        img = np.array(raw)[:, :, :3]

        # 1. 8 个房间
        room_centers_abs = self._get_room_centers()
        room_centers_rel = [(x - self.map_region["left"], y - self.map_region["top"]) for x, y in room_centers_abs]
        room_states = []
        for rel in room_centers_rel:
            h, s, v = self._sample_point(img, rel)
            cleared = v > self.BRIGHTNESS_CLEARED and s > 30
            room_states.append(cleared)

        # 2. 副本入口
        er = self.entry_region_rel
        entry_img = img[er["top"]:er["top"]+er["height"], er["left"]:er["left"]+er["width"]]
        in_dungeon = False
        if entry_img.size > 0:
            hsv = cv2.cvtColor(entry_img, cv2.COLOR_BGR2HSV)
            in_dungeon = np.mean(hsv[:, :, 1]) > 20

        # 3. 状态码
        code = "".join("1" if c else "0" for c in room_states)
        return MapState(rooms=room_states, in_dungeon=in_dungeon, state_code=code)


    def save_map_debug(self):
        """保存带网格的调试图"""
        with mss.mss() as sct:
            raw = sct.grab(self.map_region)
        img = np.array(raw)[:, :, :3].copy()
        centers = self._get_room_centers()
        for i, (abs_x, abs_y) in enumerate(centers):
            rel_x = abs_x - self.map_region["left"]
            rel_y = abs_y - self.map_region["top"]
            # cv2.circle(img, (rel_x, rel_y), 10, (0, 255, 0), 2)
            # cv2.putText(img, str(i+1), (rel_x-15, rel_y-15), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0,255,0), 2)
        er = self.entry_region_rel
        cv2.rectangle(img, (er["left"], er["top"]), (er["left"]+er["width"], er["top"]+er["height"]), (255,0,0), 2)
        cv2.imwrite("map_debug.png", img)
        print("已保存 map_debug.png")

    # ==================== 按键与循环 ====================

    def auto_cast_loop(self):
        print(f"\n技能 + 地图监控已启动！间隔: {self.release_interval}s")
        self.running = True
        try:
            while self.running:
                skills = self.detect_all_skills()
                map_state = self.detect_map_state()
                now = time.time()

                # 输出状态
                room_str = "".join("通" if c else "未" for c in map_state.rooms)
                dungeon = "进行中" if map_state.in_dungeon else "未进入"
                print(f"\r[副本: {dungeon}] [房间: {room_str}] [技能: {sum(1 for v in skills.values() if v=='available')}] ", end="", flush=True)

                # 未进入 → 点击入口
                if not map_state.in_dungeon:
                    print("\n未进入副本，点击入口...")
                    cx = self.map_region["left"] + self.entry_region_rel["left"] + self.entry_region_rel["width"] // 2
                    cy = self.map_region["top"] + self.entry_region_rel["top"] + self.entry_region_rel["height"] // 2

                    time.sleep(3.0)
                    continue

                # 8 房全通 → 按 Enter
                if all(map_state.rooms):
                    print("\n所有房间已通关！按 Enter 继续...")
                    self.keyboard.press(Key.enter)
                    self.keyboard.release(Key.enter)
                    time.sleep(3.0)
                    continue

                # 正常释放
                for key in self.release_order:
                    if not self.running: break
                    if skills.get(key) != "available": continue
                    if now - self.last_release_time < self.release_interval:
                        time.sleep(0.05)
                        continue
                    press_key(key)
                    self.last_release_time = now
                    time.sleep(0.05)
                    break

                time.sleep(0.1)
        except KeyboardInterrupt:
            print("\n停止")
        finally:
            self.running = False


    def release_skills(self, release_order=None):
        self.running = True
        try:
            while self.running:
                skills = self.detect_all_skills()
                now = time.time()

                release_order = release_order or self.release_order

                press_key("right")
                time.sleep(0.1)
                # 正常释放
                for key in release_order:
                    if not self.running: break
                    if skills.get(key) != "available": continue
                    if now - self.last_release_time < self.release_interval:
                        time.sleep(0.05)
                        continue
                    press_key(key)
                    self.last_release_time = now
                    time.sleep(0.05)
                    break

                time.sleep(self.release_interval)
        except KeyboardInterrupt:
            print("\n停止")
        finally:
            self.running = False


    def start(self):
        t = threading.Thread(target=self.auto_cast_loop, daemon=True)
        t.start()
        return t

    def stop(self):
        self.running = False

    def debug_map(self):
        with mss.mss() as sct:
            raw = sct.grab(self.map_region)
        img = np.array(raw)[:, :, :3].copy()

        # 画小人
        # pos = self.find_blue_player(img, debug=True)
        # print("pos",pos)
        while 1:
            self.update_map_state()
            time.sleep(2)

        # 画房间
        for i, (abs_x, abs_y) in enumerate(self._get_room_centers()):
            rel_x = abs_x - self.map_region["left"]
            rel_y = abs_y - self.map_region["top"]
            color = (0, 255, 0) if i in self.cleared_rooms else (0, 0, 255)
            cv2.circle(img, (rel_x, rel_y), 20, color, 3)
            cv2.putText(img, str(i+1), (rel_x-10, rel_y-10), cv2.FONT_HERSHEY_SIMPLEX, 0.7, color, 2)

        # cv2.imshow("Map Debug", img)
        # cv2.waitKey(5000)

    def update_map_state(self):

        # 1. 当前房间
        current = self.get_current_room()

        # 2. 闪烁房间
        flashing = self.detect_flashing_rooms()

        # 3. 更新房间状态
        print("shaining",current, flashing)


def composer_machiner():
    
    caster = DNFSkillAutoCaster(release_interval=1.3)

    expect_room_time = time.time()
    while True:

        room_num = caster.get_current_room()
        print("shaining",room_num)
        if room_num < 0:
            press_key("alt+s")
            time.sleep(0.5)
            press_key("alt+w")
            time.sleep(0.5)
            press_key("f10")
            time.sleep(1)
            continue

        
        if room_num == 0:
            press_key("alt+right")
            time.sleep(1)
            continue

        expect_room_time = time.time()
        if room_num <=4:
            t = threading.Thread(target=caster.release_skills, daemon=True)
            t.start()
            time.sleep(1)
            for _ in range(10):
                rooms = caster.detect_flashing_rooms()
                print("rooms",rooms)
                if len(rooms) > 0 or len(rooms) <=2:
                    caster.running = False
                    t.join()
                    press_key("alt+right")
                    break
                time.sleep(1)

        if room_num == 5:
            print("black boss --------------")
            # deep black
            press_key("tab")
            
            t = threading.Thread(target=caster.release_skills, daemon=True)
            t.start()
            time.sleep(15)
            try:
                for _ in range(30):
                    rooms = caster.detect_flashing_rooms()
                    print("rooms",rooms)
                    if len(rooms) == 1 and rooms[0] == 4:
                        break
                    time.sleep(1)
            finally:
                caster.running = False
                t.join()
                press_key("alt+right")
                time.sleep(1.5)
            

        if room_num == 6:
            print("boss -----------------")
            # deep black
            press_key("tab")
            
            t = threading.Thread(target=caster.release_skills, daemon=True)
            t.start()
            time.sleep(5)
            caster.running = False
            t.join()
            press_key("f10")
            time.sleep(0.5)
            press_key("alt+right")
            time.sleep(1.5)


                    
                

    # detector


# ==================== 主程序 ====================
if __name__ == "__main__":
    composer_machiner()
    # time.sleep(3)
    # print("press")
    caster = DNFSkillAutoCaster(release_interval=1.3)

    # caster.keyboard.press("w")
    # time.sleep(0.05)
    # caster.keyboard.release("w")
    
    # press_key("q")
    # time.sleep(0.05)
    # press_key("alt+right")
    caster.debug_map()

    # # 第一次运行：保存调试图
    # caster.save_map_debug()
    # input("请查看 map_debug.png，确认 8 个绿点在房间中心，红框在入口。按回车继续...")

    # thread = caster.start()
    # try:
    #     while True:
    #         time.sleep(1)
    # except KeyboardInterrupt:
    #     caster.stop()
    #     print("\n程序退出。")